﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Net;
using System.Xml;

using Utilities;
using System.Data.OleDb;

using System.Globalization;
using Google.GData.Client;

namespace LicenseManager
{


    public class ZohoAuthorizationException : Exception
    { 
        
    }

    public class ZohoLicenseBlocked : Exception
    {
    }

    public class ZohoLicenseExpired : Exception
    {

    }

    public class ZohoUserDataException : Exception
    {


    }

    public class ZohoLicenseManager
    {
        private static string ZOHO_API_KEY = "QS-0cQOuAiISAYqK3SfNO*IXGXPbIEgBkQaMGWeIdlI$";
        private static string ZOHO_SERVICE = "ZohoCRM";
        private static string ZOHO_API_URL = "https://accounts.zoho.com/";
        private static string ZOHO_CRM_URL = "http://crm.zoho.com/"; 

        private string m_Ticket { get; set; }

        private string m_UserName { get; set; }
        private string m_Password { get; set; }
        private DbOperations m_dbOperations;
        private ZohoTypes.ZohoContact m_contact;

        public DateTime m_CRMTime {get; set;}
        private static int TRIAL_PERIOD = 60; //trial period is 60 days. 


        public ZohoLicenseManager(string username, string password, DbOperations dbOperations)
        {
            m_UserName = username;
            m_Password = password;
            m_Ticket = ""; 
            m_dbOperations = dbOperations;
            m_contact = null;
            m_CRMTime = DateTime.Now;  
        }

        public void Login() 
        {
            //https://accounts.zoho.com/login?servicename=[ZohoCRM]&FROM_AGENT=true&LOGIN_ID=[Zoho Username/Email Address]&PASSWORD=[Password]


            string loginRequestString = ZOHO_API_URL +
                                        "login?servicename=" +
                                        ZOHO_SERVICE + "&" +
                                        "FROM_AGENT=true" + "&" +
                                        "LOGIN_ID=" + m_UserName + "&" +
                                        "PASSWORD=" + m_Password; 

            HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(loginRequestString);
            loginRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
            loginRequest.Proxy = Google.GData.Client.Utilities.CommonOperations.GetProxy();
            //loginRequest.Proxy = Utilities
            loginRequest.Method = "GET"; 

            HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse ();

            Stream receiveStream = loginResponse.GetResponseStream();

            // Pipes the stream to a higher level stream reader with the required encoding format. 
            StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

            string responseContent = readStream.ReadToEnd();
            loginResponse.Close();
            readStream.Close();

            //Analyze Response. 
            char[] seps = { '\n','\r' };
            string[] responseValues = responseContent.Split(seps);

            if (GetLoginResult(responseValues) != true)
                throw new ZohoAuthorizationException();

            m_Ticket = GetLoginTicket(responseValues);
            m_CRMTime = GetCRMTime(responseValues); 

            Console.Write(responseContent);
        }

        public void Logout()
        { 
            //NOP
        }

        public void LoadRegisteredUser()
        {
            try
            {
                string email = m_dbOperations.LookForContact();
                this.m_contact = this.SearchForContact(email);

            }
            catch (System.Exception ex)
            {
                Utilities.TraceWrapper.LogException("RegisteredContactUpdate error:" + ex.Message, ex);
                throw new ZohoUserDataException(); 
            }
        }

        public ZohoTypes.ZohoContact SearchForContact(string email)
        {
            ZohoTypes.ZohoContact contact = null;

            try
            {
                //http:// crm.zoho.com/crm/private/xml/Leads/getAllSearchRecords?apikey=[API Key]&ticket=[Ticket]
                string loginRequestString = ZOHO_CRM_URL + "crm/private/xml/Contacts/getAllSearchRecords?" +
                                            "apikey=" + ZOHO_API_KEY + "&" +
                                            "ticket=" + m_Ticket +  "&" +
                                            "searchWord=" + email;


                HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(loginRequestString);
                loginRequest.Credentials = CredentialCache.DefaultCredentials;
                loginRequest.Proxy = Google.GData.Client.Utilities.CommonOperations.GetProxy();
                loginRequest.Method = "GET";

                HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();

                Stream receiveStream = loginResponse.GetResponseStream();

                // Pipes the stream to a higher level stream reader with the required encoding format. 
                XmlTextReader xmlReader = new XmlTextReader(receiveStream);

             
                contact = GetZohoContact(xmlReader);

                loginResponse.Close();
                receiveStream.Close();
            }
            catch (WebException e)
            {
                System.Diagnostics.Trace.WriteLine("SearchForContact error: " + e.StackTrace);
            }

            return contact; 
        }

        public void UpdateContact(ZohoTypes.ZohoContact contact)
        {

            StringBuilder xmlData = new StringBuilder();

            xmlData.AppendLine(); 
            xmlData.AppendLine("<Contacts>");
            
            xmlData.Append("<row no="); 
            xmlData.Append('"');
            xmlData.Append('1');
            xmlData.Append('"');
            xmlData.Append(">");

            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Last Login");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(m_CRMTime.AddMinutes(1).ToString("yyyy-MM-dd hh:mm:ss") + "</fieldlabel>" );

            
            xmlData.AppendLine(); 
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Last Name");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.LastName + "</fieldlabel>");
            xmlData.AppendLine(); 
            
            
            xmlData.AppendLine("</row>");
            xmlData.AppendLine("</Contacts>");

             

            //http://crm.zoho.com/crm/private/xml/Leads/updateRecords?apikey=[API Key]&ticket=[Ticket]

            string loginRequestString = ZOHO_CRM_URL + "crm/private/xml/Contacts/updateRecords?" +
                                        "apikey=" + ZOHO_API_KEY + "&" +
                                        "ticket=" + m_Ticket + "&" +
                                        "xmlData=" + xmlData.ToString() + "&" +
                                        "id=" + contact.ID;
                                        
                                        

            try
            {
                HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(loginRequestString);

                loginRequest.Credentials = CredentialCache.DefaultCredentials;
                loginRequest.Proxy = Google.GData.Client.Utilities.CommonOperations.GetProxy();
                loginRequest.Method = "POST";
                

                HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();

                Stream receiveStream = loginResponse.GetResponseStream();
                StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

                string s = readStream.ReadToEnd(); 
                //Console.Write(readStream.ReadToEnd());


                loginResponse.Close();
                receiveStream.Close();
            }
            catch(WebException ex)
            {
                System.Diagnostics.Trace.WriteLine("UpdateContact error: " + ex.StackTrace);
            }
        }

        public void InsertContact(ZohoTypes.ZohoContact contact)
        {
            
            StringBuilder xmlData = new StringBuilder();

            xmlData.AppendLine();
            xmlData.AppendLine("<Contacts>");
            xmlData.AppendLine();

            xmlData.Append("<row no=");
            xmlData.Append('"');
            xmlData.Append('1');
            xmlData.Append('"');
            xmlData.Append(">");

            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("First Name");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.FirtsName + "</fieldlabel>");


            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Email");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.Email + "</fieldlabel>");


            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Phone");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.Phone + "</fieldlabel>");

            
            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Last Login");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(this.m_CRMTime.ToString("yyyy-MM-dd hh:mm:ss") + "</fieldlabel>");

            // Add the information about first login's time
            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("First Login");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(this.m_CRMTime.ToString("yyyy-MM-dd hh:mm:ss") + "</fieldlabel>");

            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("ExpiredOn");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(this.m_CRMTime.AddDays(TRIAL_PERIOD).ToString("yyyy-MM-dd hh:mm:ss") + "</fieldlabel>");


            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Last Name");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.LastName + "</fieldlabel>");
            xmlData.AppendLine();

            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Company");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.Company + "</fieldlabel>");
            xmlData.AppendLine();


            xmlData.AppendLine();
            xmlData.Append("<fieldlabel value=");
            xmlData.Append('"');
            xmlData.Append("Mailing Country");
            xmlData.Append('"');
            xmlData.Append(">");
            xmlData.Append(contact.Country + "</fieldlabel>");
            xmlData.AppendLine();

            xmlData.AppendLine("</row>");
            xmlData.AppendLine("</Contacts>");



            //http://crm.zoho.com/crm/private/xml/Leads/updateRecords?apikey=[API Key]&ticket=[Ticket]

            string loginRequestString = ZOHO_CRM_URL + "crm/private/xml/Contacts/insertRecords?" +
                                        "apikey=" + ZOHO_API_KEY + "&" +
                                        "ticket=" + m_Ticket + "&" +
                                        "xmlData=" + xmlData.ToString();
                                        

            try
            {
                HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(loginRequestString);
                loginRequest.Credentials = CredentialCache.DefaultCredentials;
                loginRequest.Proxy = Google.GData.Client.Utilities.CommonOperations.GetProxy();

                //Stream requestStream = loginRequest.GetRequestStream();
                //requestStream.Write(xmlData.
                loginRequest.Method = "POST";

                HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();

                Stream receiveStream = loginResponse.GetResponseStream();
                XmlTextReader xmlReader = new XmlTextReader(receiveStream);


                ZohoTypes.ZohoContact tempContact = GetZohoContact(xmlReader);
                if (tempContact != null)
                    contact.ID = tempContact.ID;

                loginResponse.Close();
                receiveStream.Close();
            }
            catch (WebException ex)
            {
                System.Diagnostics.Trace.WriteLine("InsertContact error: " + ex.StackTrace);
            }
        }

        private bool GetLoginResult(string[] responseValues)
        {
            foreach (string param in responseValues)
            {
                if (param.StartsWith("RESULT="))
                {
                    string value = param.Substring(7);
                    if (value.Equals("TRUE"))
                        return true;
                }
            }

            return false; 
        }


        private DateTime GetCRMTime(string[] responseValues)
        {
            foreach (string param in responseValues)
            {
                if (param.StartsWith("#") & param.Length > 1)
                {
                    DateTime value;
                    try
                    {
                        value = DateTime.ParseExact(param.Substring(1),
                        "ddd MMM dd HH:mm:ss PST yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
                    }
                    catch (Exception ex)
                    {
                        value = DateTime.ParseExact(param.Substring(1),
                        "ddd MMM dd HH:mm:ss PDT yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
                    }
                }
            }

            return DateTime.Now;
        }

        private string GetLoginTicket(string[] responseValues)
        {
            string ticket = "";
            foreach (string param in responseValues)
            {
                if (param.StartsWith("TICKET="))
                {
                    ticket = param.Substring(7);
                    return ticket; 
                }
            }
            return ticket; 
        }

        private ZohoTypes.ZohoContact GetZohoContact(XmlTextReader reader)
        {
            ZohoTypes.ZohoContact contact = null;
            string FirstName = "";
            string LastName = "";
            string ContactId = "";
            DateTime LastLogin = new DateTime(1899, 1, 1);
            //Read information about first login
            DateTime FirstLogin = new DateTime(1899, 1, 1);
            DateTime ExpiredOn = new DateTime(1899, 1, 1); 
            
            string Email = "";
            string Phone = "";
            bool Blocked = false; 
            string Company = "";

            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    if (reader.Name == "fieldlabel")
                    {
                        if (reader.HasAttributes)
                        {
                            if(reader.GetAttribute("value").Equals("CONTACTID") || reader.GetAttribute("value").Equals("Id"))
                            {
                                reader.Read(); 
                                ContactId = reader.Value;
                            } 
                            else
                            if (reader.GetAttribute("value").Equals("First Name"))
                            {
                                reader.Read();
                                FirstName = reader.Value;
                            }
                            else
                            if (reader.GetAttribute("value").Equals("Last Name"))
                            {
                                reader.Read();
                                LastName = reader.Value;
                            }
                            else
                            if (reader.GetAttribute("value").Equals("Email"))
                            {
                                reader.Read();
                                Email = reader.Value;
                            }    
                            else
                            if (reader.GetAttribute("value").Equals("Phone"))
                            {
                                reader.Read();
                                Phone = reader.Value;
                            }   
                            else
                            if (reader.GetAttribute("value").Equals("Last Login"))
                            {
                                reader.Read();
                                if (reader.Value != "null")
                                    LastLogin = DateTime.Parse(reader.Value);
                            }
                            else
                            if (reader.GetAttribute("value").Equals("First Login"))
                            {
                                reader.Read();
                                if (reader.Value != "null")
                                    FirstLogin = DateTime.Parse(reader.Value);
                            }
                            else
                            if (reader.GetAttribute("value").Equals("ExpiredOn"))
                            {
                                reader.Read();
                                if (reader.Value != "null")
                                    ExpiredOn = DateTime.Parse(reader.Value);
                            }
                            else
                                if (reader.GetAttribute("value").Equals("Blocked"))
                                {
                                    reader.Read();
                                    if (reader.Value != "null")
                                        Blocked = bool.Parse(reader.Value);
                                }
                                else
                            if (reader.GetAttribute("value").Equals("Company"))
                            {
                                reader.Read();
                                Company = reader.Value;
                            }
                        }

                    }
                }
            }

            if (ContactId != "")
            {
                contact = new ZohoTypes.ZohoContact();
                contact.ID = ContactId;
                contact.FirtsName = FirstName;
                contact.LastName = LastName;
                contact.LastLogin = LastLogin;
                contact.FirstLogin = FirstLogin;
                contact.ExpiredOn = ExpiredOn; 
                contact.Email = Email;
                contact.Phone = Phone;
                contact.Company = Company;
                contact.Blocked = Blocked;
            }
            return contact; 
        }

        public void RegisteredContactUpdate()
        {
            try
            {
                this.UpdateContact(m_contact); 
            }
            catch (System.Exception ex)
            {
                Utilities.TraceWrapper.LogException("RegisteredContactUpdate error:" + ex.Message, ex);
            }
        }

        public bool RegisteredContactBlocked()
        {
            return m_contact.Blocked; 
        }

        public bool RegisteredLicenseExpired()
        {
            if (m_contact.ExpiredOn.Subtract(this.m_CRMTime).Days < 0) return true; 
            return false; 
        }
        
    }
}
